package com.photoveil;

import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Bitmap.CompressFormat;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

public class PhotoVeilActivity extends Activity{
    private static final int MAX_TRANSPARENCY_VALUE = 255;
    private static final int DEFAULT_TRANSPARENCY_VALUE = 127;
    private static final CharSequence[] ADD_MEDIA_ITEMS = {"Image", "Text"};
    private static final int IMAGE_ITEM_INDEX = 0;
    private static final int TEXT_ITEM_INDEX = 1;
    private static final int SELECT_PICTURE_REQUEST_CODE = 1;
    private static final int EDIT_TEXT_REQUEST_CODE = 2;
    private static final int ADD_TEXT_REQUEST_CODE = 3;

    
    private final Context context = this;
    
    private static ChangeLog changeLog = ChangeLog.getInstance();
    private static ThumbnailHelper thumbnailHelper = ThumbnailHelper.getInstance();
    private static SeekBar transparencySeekbar;
    private static TransparencySeekBarChangeListener transparencySeekbarListener;
    private static int numLayers = 0;
    private String selectedImagePath;
    private String filename = "";
    
    private static List<Thumbnail> thumbnails = new ArrayList<Thumbnail>();
    private static Layer currentLayer;
    private static Layer cowLayer;
    
    private static RelativeLayout layeredImages;
    private static LinearLayout thumbnailLayout;
    private static Button addButton;
    private static Button editButton;
    private static Button deleteButton;
    private static Button saveButton;
    
    
	/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        layeredImages = (RelativeLayout) findViewById(R.id.layered_layout);
        thumbnailLayout = (LinearLayout) findViewById(R.id.thumbnail_layout);
        
        ImageView cowImage = (ImageView) findViewById(R.id.cow_image);		//blank layer (black)
        ImageView cowImageThumbnail = (ImageView) findViewById(R.id.cow_image_thumbnail);
        
        cowLayer = new ImageLayer(cowImage, cowImageThumbnail, MAX_TRANSPARENCY_VALUE);
        currentLayer = cowLayer;
        
        initializeTransparencySeekBar(cowLayer);
        initializeButtons();
        
        setScreenItemsInvisible();
    }
    
    public void initializeButtons() {
    	addButton = (Button) findViewById(R.id.addButton);
    	editButton = (Button) findViewById(R.id.editButton);
    	deleteButton = (Button) findViewById(R.id.deleteButton);
    	saveButton = (Button) findViewById(R.id.saveButton);
    	
    	deleteButton.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				deleteLayer(currentLayer);
				changeLog.addChange(new Change(currentLayer, Change.CHANGE_TYPE_DELETE_LAYER, numLayers, numLayers));
				
				if(numLayers == 0) {
					setScreenItemsInvisible();
				}
			}
		});
    	
    	editButton.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				if(currentLayer.getLayerType() == Layer.IMAGE_LAYER_TYPE) {
					//add image preferences (B/W, sepia, brightness, etc.)
				} else if (currentLayer.getLayerType() == Layer.TEXT_LAYER_TYPE) {
					Intent intent = new Intent(context, TextEditActivity.class);
					Bundle bundle = new Bundle();
					bundle.putSerializable("text_preferences", currentLayer.getPreferences());
					intent.putExtras(bundle);
		    		startActivityForResult(intent, EDIT_TEXT_REQUEST_CODE);
				}
				
			}
		});
    	
    	
    	saveButton.setOnClickListener(new View.OnClickListener() {
			
			public void onClick(View v) {				
				final EditText editText = new EditText(context);
				editText.setText(filename);
				
				AlertDialog.Builder builder = new AlertDialog.Builder(context);
				builder.setTitle("Enter a file name");
				builder.setView(editText);
				builder.setPositiveButton("Okay", new DialogInterface.OnClickListener() {
					
					public void onClick(DialogInterface dialog, int which) {
						filename = editText.getText().toString();
						if ("".equals(filename) || filename.contains(" ")) {
							filename = Long.toString(System.currentTimeMillis());
						}
						saveImage(filename);
						
					}
				});
				
				builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						dialog.cancel();
					}
				});
				
				AlertDialog alert = builder.create();
				alert.show();
				
				
			}
			
			public void saveImage(String fileName) {
				File sdCard = Environment.getExternalStorageDirectory();
				FileOutputStream fOut = null;
				File file = new File(sdCard, fileName +".jpg");
				try {
					fOut = new FileOutputStream(file);
					
					Bitmap bitmap = Bitmap.createBitmap(layeredImages.getWidth(), layeredImages.getHeight(), Bitmap.Config.ARGB_8888);
					Canvas canvas = new Canvas(bitmap);
					layeredImages.draw(canvas);
					boolean success = bitmap.compress(CompressFormat.JPEG, 100, fOut);
					
					fOut.flush();
					fOut.close();
					Toast.makeText(getApplicationContext(), fileName + ".jpg saved to SD card", Toast.LENGTH_SHORT).show();
					Log.i("PhotoVeil", "Image saved to " + sdCard + ". SuccessValue: " + success);
				} catch (Exception e) {
					Toast.makeText(getApplicationContext(), "Error occurred while saving", Toast.LENGTH_SHORT).show();
					Log.e("PhotoVeil", "Error occurred while saving: " + e.getMessage());
					e.printStackTrace();
					return;
				}
			}
		});
    	
    	addButton.setOnClickListener(new View.OnClickListener() {
			
			public void onClick(View v) {	

				AlertDialog.Builder builder = new AlertDialog.Builder(context);
				builder.setTitle("Add media");
				builder.setItems(ADD_MEDIA_ITEMS, new DialogInterface.OnClickListener() {
				    public void onClick(DialogInterface dialog, int item) {
				    	if(item == IMAGE_ITEM_INDEX) {
				    		Intent intent = new Intent(Intent.ACTION_GET_CONTENT);  
				    		intent.setType("image/*");
				    		startActivityForResult(intent, SELECT_PICTURE_REQUEST_CODE);
				    		
				    	} else if (item == TEXT_ITEM_INDEX) {
				    		Intent intent = new Intent(context, TextEditActivity.class);
				    		startActivityForResult(intent, ADD_TEXT_REQUEST_CODE);
				    	}
				    	
				    }
				    
				});
				builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						dialog.cancel();
					}
				});
				
				AlertDialog alert = builder.create();
				alert.show();
			}
		});
    }
    
    public void initializeTransparencySeekBar(Layer layer) {
    	transparencySeekbarListener = new TransparencySeekBarChangeListener(getApplicationContext(), layer);
    	
    	transparencySeekbar = (SeekBar) findViewById(R.id.transparency_seekBar);
        transparencySeekbar.setMax(MAX_TRANSPARENCY_VALUE);
        transparencySeekbar.setProgress(MAX_TRANSPARENCY_VALUE-5);
        transparencySeekbar.setOnSeekBarChangeListener(transparencySeekbarListener);
    }
    
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            if (requestCode == SELECT_PICTURE_REQUEST_CODE) {
                Uri selectedImageUri = data.getData();
                selectedImagePath = getPath(selectedImageUri);
                Bitmap photoBitmap = BitmapFactory.decodeFile(selectedImagePath);
                if (photoBitmap != null) {
                	addNewImageLayer(photoBitmap);
                }
                setScreenItemsVisible();
            }
            else if (requestCode == ADD_TEXT_REQUEST_CODE) {
            	Bundle bundle = data.getExtras();
            	
            	if (bundle != null) {
            		TextPreference textPreference = (TextPreference) bundle.get("text_preferences");
            		if (textPreference.getText() != "") {
            			addNewTextLayer(textPreference);
            			Log.i("PhotoVeil", "Returned text value: " + textPreference.getText());
            		} else {
            			Log.i("PhotoVeil", "Blank text value returned");
            		}
            	}
            	setScreenItemsVisible();
            }
            else if (requestCode == EDIT_TEXT_REQUEST_CODE) {
            	Bundle bundle = data.getExtras();
            	
            	if (bundle != null) {
            		TextPreference textPreference = (TextPreference) bundle.get("text_preferences");
            		((TextLayer)currentLayer).setPreferences(textPreference);
            		editText(currentLayer);
            		Log.i("PhotoVeil", "Updated text layer: " + textPreference.getText());
            	}
            }
        }
    }

    public String getPath(Uri uri) {
        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = managedQuery(uri, projection, null, null, null);
        int column_index = cursor
                .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    }
    
    
    
    public void addNewImageLayer(Bitmap bitmap) {
    	ImageView image = addNewImage(bitmap);
		ImageView thumbnailImage = addNewThumbnail(bitmap);
		
		Layer newLayer;
		if (numLayers == 0) {
			newLayer = new ImageLayer(image, thumbnailImage, MAX_TRANSPARENCY_VALUE);
		} else {
			newLayer = new ImageLayer(image, thumbnailImage, DEFAULT_TRANSPARENCY_VALUE);
		}
		
		addThumbnailListener(newLayer);
		layeredImages.addView(image);
		thumbnailLayout.addView(thumbnailImage);
		
		changeLog.addChange(new Change(newLayer, Change.CHANGE_TYPE_NEW_LAYER, numLayers, ++numLayers));
    }
    
    public void addNewTextLayer(TextPreference textPreference) {
    	AlphaTextView alphaTextView = addNewText(textPreference);
    	Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.text);
		ImageView thumbnailImage = addNewThumbnail(bitmap);
		
		Layer newLayer = new TextLayer(alphaTextView, thumbnailImage, DEFAULT_TRANSPARENCY_VALUE, textPreference);
		addThumbnailListener(newLayer);
		
		layeredImages.addView(alphaTextView);
		thumbnailLayout.addView(thumbnailImage);
		changeLog.addChange(new Change(newLayer, Change.CHANGE_TYPE_NEW_LAYER, numLayers, ++numLayers));
    }
    
    private ImageView addNewImage(Bitmap photoBitmap) {
		ImageView image = new ImageView(getApplicationContext());
		image.setImageBitmap(photoBitmap);

		RelativeLayout.LayoutParams params = (LayoutParams) cowLayer.getImage().getLayoutParams();
		
		image.setLayoutParams(params);
		return image;
	}
    
    private AlphaTextView addNewText(TextPreference textPreference) {
		AlphaTextView alphaTextView = new AlphaTextView(context);
		alphaTextView.setText(textPreference.getText());
		alphaTextView.setTextSize(textPreference.getSize());
		alphaTextView.setTypeface(textPreference.getFontValue(), textPreference.getStyleValue());
		alphaTextView.setTextColor(textPreference.getColour());
		setPaddingOnTextView(alphaTextView, textPreference);		
		
		LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
		params.addRule(textPreference.getHorizontalPosition(), R.id.cow_image);
		params.addRule(textPreference.getVerticalPosition(), R.id.cow_image);
		alphaTextView.setLayoutParams(params);
		
		return alphaTextView;
	}
    
    private void editText(Layer layer) {
    	AlphaTextView alphaTextView = (AlphaTextView) layer.getImage();
    	TextPreference textPreference = (TextPreference) layer.getPreferences();
    	
    	alphaTextView.setText(textPreference.getText());
		alphaTextView.setTextSize(textPreference.getSize());
		alphaTextView.setTypeface(textPreference.getFontValue(), textPreference.getStyleValue());
		alphaTextView.setTextColor(textPreference.getColour());
		setPaddingOnTextView(alphaTextView, textPreference);		
		
		LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
		params.addRule(textPreference.getHorizontalPosition(), R.id.cow_image);
		params.addRule(textPreference.getVerticalPosition(), R.id.cow_image);
		alphaTextView.setLayoutParams(params);
		
		layer.setAlphaValue(layer.getAlphaValue());
    }
    
    private void setPaddingOnTextView(TextView textView, TextPreference textPreference) {
    	int horizontalPosition = textPreference.getHorizontalPosition();
    	int verticalPosition = textPreference.getVerticalPosition();
    	
    	int leftPadding = 0;
		int rightPadding = 0;
		int topPadding = 0;
		int bottomPadding = 0;
		
		if (horizontalPosition == RelativeLayout.ALIGN_LEFT) {
			leftPadding = 15;
		} else if (horizontalPosition == RelativeLayout.ALIGN_RIGHT) {
			rightPadding = 15;
		}
		
		if (verticalPosition == RelativeLayout.ALIGN_TOP) {
			topPadding = 10;
		} else if (verticalPosition == RelativeLayout.ALIGN_BOTTOM) {
			bottomPadding = 10;
		}
		
		textView.setPadding(leftPadding, topPadding, rightPadding, bottomPadding);
    }
    
    private ImageView addNewThumbnail(Bitmap photoBitmap) {
		final ImageView thumbnailImage = new ImageView(getApplicationContext());
		thumbnailImage.setImageBitmap(photoBitmap);
		
		LayoutParams thumbnailParams = new LayoutParams(59,48);		//my phone thumbnails
//		LayoutParams thumbnailParams = new LayoutParams(85,73);		//emulator thumbnails
		thumbnailParams.setMargins(10, 0, 10, 0);
		
		thumbnailImage.setLayoutParams(thumbnailParams);

		return thumbnailImage;
	}
    
    private void addThumbnailListener(final Layer newLayer) {
		final ImageView thumbnailImage = (ImageView)newLayer.getThumbnailImage();
		transparencySeekbarListener.setLayer(newLayer);
		transparencySeekbar.setProgress(newLayer.getAlphaValue());
		thumbnails.add(new Thumbnail(thumbnailImage));
		thumbnailHelper.clearBackgrounds(thumbnails);
		thumbnailHelper.setHighlightedBackground(thumbnailImage);
		currentLayer = newLayer;
		
		thumbnailImage.setOnClickListener(new View.OnClickListener() {
			
			public void onClick(View v) {
				transparencySeekbarListener.setLayer(newLayer);
				transparencySeekbar.setProgress(newLayer.getAlphaValue());
				thumbnails.add(new Thumbnail(thumbnailImage));
				thumbnailHelper.clearBackgrounds(thumbnails);
				thumbnailHelper.setHighlightedBackground(thumbnailImage);
				currentLayer = newLayer;
			}
		});
	}
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.preference_menu, menu);
        return true;
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle item selection
        switch (item.getItemId()) {
            case R.id.new_image:
            	performNew();
                return true;
            case R.id.undo:
            	performUndo();
                return true;
            case R.id.redo:
            	performRedo();
            	return true;
            
            default:
                return super.onOptionsItemSelected(item);
        }
    }
    
    public void performNew() {
    	int numImageLayers = layeredImages.getChildCount();
    	int numThumbnailLayers = thumbnailLayout.getChildCount();
    	
    	for (int i=1; i < numImageLayers; i++) {
    		layeredImages.getChildAt(i).setVisibility(View.GONE);
    	}
    	
    	thumbnailHelper.clearBackgrounds(thumbnails);
    	for (int i=2; i < numThumbnailLayers; i++) {
    		thumbnailLayout.getChildAt(i).setVisibility(View.GONE);
    	}
    	
    	numLayers = 0;
    	filename = "";
    	changeLog.clearAllChanges();
    	setScreenItemsInvisible();
    }
    
    public void performUndo() {
    	Change lastChange = changeLog.getLastChange();
		if (lastChange == null) {
			return;
		}
		
		if(lastChange.getChangeType() == Change.CHANGE_TYPE_TRANSPARENCY) {
			lastChange.getLayer().setAlphaValue(lastChange.getOldValue());
			Log.i("PhotoVeil","Undo pressed. Alpha value changed to " + lastChange.getOldValue());
		} else if (lastChange.getChangeType() == Change.CHANGE_TYPE_NEW_LAYER) {
			deleteLayer(lastChange.getLayer());
			Log.i("PhotoVeil","Undo pressed. Image at layer " + lastChange.getOldValue() + " was removed");
			if (numLayers == 0) {
				setScreenItemsInvisible();
			}
		} else if (lastChange.getChangeType() == Change.CHANGE_TYPE_DELETE_LAYER) {
			lastChange.getLayer().getImage().setVisibility(View.VISIBLE);
			lastChange.getLayer().getThumbnailImage().setVisibility(View.VISIBLE);
			Log.i("PhotoVeil","Redo pressed. Image at layer " + lastChange.getOldValue() + " was re-added");
			numLayers++;
			setScreenItemsVisible();
		}
    }
    
    public void deleteLayer(Layer layer) {
    	layer.getImage().setVisibility(View.GONE);
    	layer.getThumbnailImage().setVisibility(View.GONE);
		
		Log.i("PhotoVeil","Layer deleted");
		numLayers--;
    }
    
    public void performRedo() {
    	Change nextChange = changeLog.getNextChange();
		if (nextChange == null) {
			return;
		}

		if (nextChange.getChangeType() == Change.CHANGE_TYPE_TRANSPARENCY) {
			nextChange.getLayer().setAlphaValue(nextChange.getNewValue());
			Log.i("PhotoVeil", "Redo pressed. Alpha value changed to " + nextChange.getNewValue());
		} else if (nextChange.getChangeType() == Change.CHANGE_TYPE_NEW_LAYER) {
			nextChange.getLayer().getImage().setVisibility(View.VISIBLE);
			nextChange.getLayer().getThumbnailImage().setVisibility(View.VISIBLE);
			Log.i("PhotoVeil","Redo pressed. Image at layer " + nextChange.getOldValue() + " was re-added");
			setScreenItemsVisible();
			numLayers++;
			
		} else if (nextChange.getChangeType() == Change.CHANGE_TYPE_DELETE_LAYER) {
			deleteLayer(nextChange.getLayer());
			if (numLayers == 0) {
				setScreenItemsInvisible();
			}
			Log.i("PhotoVeil","Undo pressed. Image at layer " + nextChange.getOldValue() + " was removed");
		}
    }
    
    public void setScreenItemsInvisible() {
    	TextView layerLabel = (TextView) findViewById(R.id.layer_label);
    	TextView transparencyLabel = (TextView) findViewById(R.id.transparency_label);
    	
    	layerLabel.setVisibility(View.INVISIBLE);
    	transparencyLabel.setVisibility(View.INVISIBLE);
    	transparencySeekbar.setVisibility(View.INVISIBLE);
    	
    	editButton.setEnabled(false);
    	deleteButton.setEnabled(false);
    	saveButton.setEnabled(false);
    	
    	((ImageView)cowLayer.getImage()).setImageResource(R.drawable.startup);
    }
    
    public void setScreenItemsVisible() {
    	TextView layerLabel = (TextView) findViewById(R.id.layer_label);
    	TextView transparencyLabel = (TextView) findViewById(R.id.transparency_label);
    	
    	layerLabel.setVisibility(View.VISIBLE);
    	transparencyLabel.setVisibility(View.VISIBLE);
    	transparencySeekbar.setVisibility(View.VISIBLE);
    	
    	editButton.setEnabled(true);
    	deleteButton.setEnabled(true);
    	saveButton.setEnabled(true);
    	
    	((ImageView)cowLayer.getImage()).setImageResource(R.drawable.black);
    }
}